package tournoi.modele;

import java.io.Serializable;
import java.util.Set;

import javax.persistence.*;

/**
 * Classe permettant de definir l'objet match. Le match aura comme id un entier
 * genere automatique. On connaitre comme informations l'heure du debut du
 * match, si le match a eu une prolongation, s'il y a eu une seance de tirs aux
 * buts. Le match contiendra aussi la liste de ses buts (minutes,auteur),
 * l'equipe a domicile et l'equipe jouant a l'exterieur. De plus on connaitra
 * l'arbitre du match
 * 
 * @author Florent Champigny, Kevin De Jesus Ferreira and Julien Mialon
 * 
 */
@Entity
public class Match implements Serializable {

	private static final long serialVersionUID = 7031660737429543929L;

	/**
	 * Correspond a l'identifiant du joueur
	 */
	@Id
	@GeneratedValue
	private int id;

	/**
	 * Correspond au numero du match dans le tour
	 */
	private int numero;

	public static final int PREVU = 0;
	public static final int EN_COURS = 1;
	public static final int FINIT = 2;

	/**
	 * Etat du match, peut etre PREVU, EN_COURS ou FINIT
	 */
	private int etat = PREVU;

	/**
	 * Date et Heure de debut du match
	 */
	private String dateHeure;

	/**
	 * Permet de savoir si le match a eu une prolongation
	 */
	private boolean prolongation = false;

	/**
	 * Permet de savoir si le match a eu une seance de tirs aux buts
	 */
	private boolean tirAuButs = false;

	/**
	 * Collection contenant la liste de tout les buts du match
	 */
	@OneToMany(fetch = FetchType.EAGER)
	@OrderBy("minuteMarque")
	private Set<But> buts;

	/**
	 * Arbitre affecte au match
	 */
	@ManyToOne
	private Arbitre arbitre;

	/**
	 * Equipe jouant le match a domicile
	 */
	@ManyToOne
	private Equipe domicile;

	/**
	 * le match gagné par l'equipe domicile null si premier match
	 */
	@OneToOne
	private Match ancienMatchDomicile;

	/**
	 * Equipe jouant le match a l'exterieur
	 */
	@ManyToOne
	private Equipe exterieur;

	/**
	 * le match gagné par l'equipe exterieur null si premier match
	 */
	@OneToOne
	private Match ancienMatchExterieur;

	/**
	 * Permet de savoir, si le match est en cours, la duree de jeu qui a deja
	 * ete effectuee
	 */
	private int minuteJoue;

	/**
	 * Retourne le score d'une equipe
	 * 
	 * @param equipe
	 * @return
	 */
	public int scoreEquipe(Equipe equipe) {
		int score = 0;

		if (equipe != null && buts != null)
			for (But but : buts) {
				Joueur butteur = but.getButeur();
				Equipe equipeButteur = butteur.getEquipe();
				if (equipeButteur.getId() == equipe.getId())
					score += 1;
			}

		return score;
	}

	/**
	 * Calcul le score des tirs au but d'une equipe
	 * 
	 * @param equipe
	 *            - Equipe dont on veut connaitre le score
	 * @return - Retourne le score au tir au but de l'équipe passée en paramètre
	 */
	public int scoreEquipeTirAuBut(Equipe equipe) {
		int score = 0;

		if (this.isTirAuButs()) {
			if (equipe != null && buts != null)
				for (But but : buts) {
					if (but.isTirAuBut()) {
						Joueur butteur = but.getButeur();
						Equipe equipeButteur = butteur.getEquipe();
						if (equipeButteur.getId() == equipe.getId())
							score += 1;
					}
				}
		}
		return score;
	}

	// ########### Méthodes #######################
	/**
	 * Retourne le pourcentage de temps de jeu joue
	 */
	public int pourcentageBar() {
		if (this.prolongation) {
			return Math.round(this.minuteJoue * 100 / 120);
		} else {
			if (this.tirAuButs) {
				return 100;
			} else {
				return Math.round(this.minuteJoue * 100 / 90);

			}
		}
	}

	@Override
	public int hashCode() {
		final int prime = 31;
		int result = 1;
		result = prime * result + numero;
		return result;
	}

	@Override
	public boolean equals(Object obj) {
		if (this == obj)
			return true;
		if (obj == null)
			return false;
		if (getClass() != obj.getClass())
			return false;
		Match other = (Match) obj;
		if (numero != other.numero)
			return false;
		return true;
	}

	// ########### Affichage ######################

	public String afficherMomentMatch() {
		if (this.prolongation) {
			return "Prolongation";
		} else {
			if (this.tirAuButs) {
				return "Tirs aux buts";
			} else {
				return "Temps réglementaire";
			}
		}
	}

	// ########### Getters and Setters ############

	public Equipe getDomicile() {
		return domicile;
	}

	public void setDomicile(Equipe domicile) {
		this.domicile = domicile;
	}

	public Equipe getExterieur() {
		return exterieur;
	}

	public void setExterieur(Equipe exterieur) {
		this.exterieur = exterieur;
	}

	public int getId() {
		return id;
	}

	public void setId(int id) {
		this.id = id;
	}

	public String getDateHeure() {
		return dateHeure;
	}

	public void setDateHeure(String dateHeure) {
		this.dateHeure = dateHeure;
	}

	public boolean isProlongation() {
		return prolongation;
	}

	public void setProlongation(boolean prolongation) {
		this.prolongation = prolongation;
	}

	public boolean isTirAuButs() {
		return tirAuButs;
	}

	public void setTirAuButs(boolean tirAuButs) {
		this.tirAuButs = tirAuButs;
	}

	public Set<But> getButs() {
		return buts;
	}

	public void setButs(Set<But> buts) {
		this.buts = buts;
	}

	public Arbitre getArbitre() {
		return arbitre;
	}

	public void setArbitre(Arbitre arbitre) {
		this.arbitre = arbitre;
	}

	public int getNumero() {
		return numero;
	}

	public void setNumero(int numero) {
		this.numero = numero;
	}

	public Match getAncienMatchDomicile() {
		return ancienMatchDomicile;
	}

	public void setAncienMatchDomicile(Match ancienMatchDomicile) {
		this.ancienMatchDomicile = ancienMatchDomicile;
	}

	public Match getAncienMatchExterieur() {
		return ancienMatchExterieur;
	}

	public void setAncienMatchExterieur(Match ancienMatchExterieur) {
		this.ancienMatchExterieur = ancienMatchExterieur;
	}

	public int getMinuteJoue() {
		return minuteJoue;
	}

	public void setMinuteJoue(int minuteJoue) {
		this.minuteJoue = minuteJoue;
	}

	public int getEtat() {
		return etat;
	}

	public void setEtat(int etat) {
		this.etat = etat;
	}

	public String afficherEtat() {
		switch (etat) {
		case PREVU:
			return "prévu";
		case EN_COURS:
			return "en cours";
		case FINIT:
			return "finit";
		}
		return "";
	}

	public boolean isPrevu() {
		return etat == PREVU;
	}

	public boolean isEnCours() {
		return etat == EN_COURS;
	}

	public boolean isFinit() {
		return etat == FINIT;
	}

	public boolean isReglementaire() {
		if (!this.prolongation && !this.tirAuButs)
			return true;
		return false;
	}
}
